package com.echo.code.thread.mode.active;

import com.echo.code.thread.future.Future;
import com.echo.code.thread.future.impl.SimpleFuture;
import com.echo.code.thread.queue.BlockingQueue;
import com.echo.code.thread.queue.impl.LinkedBlockingQueue;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * ActiveServiceFactory Created by baiyap on 2018/10/6.
 */
public class ActiveServiceFactory {

  private final static BlockingQueue<ActiveMessage> QUEUE = new LinkedBlockingQueue<>();

  public static <T> T active(T instance) {
    new ActiveDaemonThread(QUEUE).start();
    // 调用JDK动态代理
    Object proxy = Proxy.newProxyInstance(instance.getClass().getClassLoader(), instance.getClass().getInterfaces(),
        new ActiveInvocationHandler<>(instance));
    return (T) proxy;
  }

  // JDK动态代理handler
  private static class ActiveInvocationHandler<T> implements InvocationHandler {

    private final T source;

    ActiveInvocationHandler(T source) {
      this.source = source;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      if (method.isAnnotationPresent(ActiveMethod.class)) {
        Object result = null;
        ActiveMessage message = ActiveMessage.builder().service(source).args(args).method(method).build();
        if (isReturnFutureType(method)) {
          Future<Object> future = new SimpleFuture<>();
          message.setResult(future);
          result = future;
        }
        QUEUE.offer(message);
        return result;
      } else {
        return method.invoke(source, args);
      }
    }

    private boolean isReturnFutureType(Method method) {
      return method.getReturnType().isAssignableFrom(Future.class);
    }
  }
}

